package relu.fbs.jfm;

import java.util.*;

import jfm.model.Types.CropType;
import relu.fbs.BadDataException;
import relu.fbs.DataValue;
import relu.fbs.xt.FBSCropData.FBSCDatum;
import relu.fbs.xt.*;
import relu.fbs.FarmData;

public class JFMCropData extends AbstractJFMCropData {
	
	/** \@return a JFMCropData object (or possibly also its corresponding setaside crop object) created from an FBSCropData object */
	public static JFMCropData[] fromFBSCropData(FBSCropData fbsd) throws BadDataException {
		JFMCropData[]  both=new JFMCropData[2];
		both[0]=null;both[1]=null;
		if ( fbsd.isBad()){
			return both;
		}
		CropType jfmct=FarmData.mapToJFMCrop.get(fbsd.cropType);
		JFMCropData main=new JFMCropData(jfmct);
		double areaweight = fbsd.getValue(FBSCDatum.AREA);
		both[0]=main;
		// Set values for main crop
		main.addDatum(JFMCDatum.AREA,areaweight);
		
		main.addDatum(JFMCDatum.AREAPAYMENT,toPerHectare(FBSCDatum.AREAPAYMENT,fbsd,areaweight),areaweight);
		main.addDatum(JFMCDatum.EO,fbsd.getValue(FBSCDatum.EO));
		main.addDatum(JFMCDatum.YIELD,fbsd.getValue(FBSCDatum.YIELD));
		double vsold=fbsd.getValue(FBSCDatum.VSOLD);
		double tsold=fbsd.getValue(FBSCDatum.TSOLD);
		double price=0;
		if ( tsold>0){
			price=vsold/tsold;
		}
		main.addDatum(JFMCDatum.PRICE,price,areaweight);
		
		if ( fbsd.getValue(FBSCDatum.AREASA) > 0 ){
			if ( !FarmData.jfmSetAsideCrops.containsKey(jfmct) ){
				throw new Error("Set aside crop type not defined for"+jfmct);
			}
			JFMCropData seta=new JFMCropData(FarmData.jfmSetAsideCrops.get(jfmct));
			both[1]=seta;
			areaweight=fbsd.getValue(FBSCDatum.AREASA);
			seta.addDatum(JFMCDatum.AREA,fbsd.getValue(FBSCDatum.AREASA));
			seta.addDatum(JFMCDatum.EO,fbsd.getValue(FBSCDatum.EOSA));
			seta.addDatum(JFMCDatum.YIELD,fbsd.getValue(FBSCDatum.YIELDSA),areaweight);
			vsold=fbsd.getValue(FBSCDatum.VSOLDSA);
			tsold=fbsd.getValue(FBSCDatum.TSOLDSA);
			price=0;
			if ( tsold>0){
				price=vsold/tsold;
			}
			seta.addDatum(JFMCDatum.PRICE,price,areaweight);
		}
		
		return both;
	}
	private static double toPerHectare(FBSCDatum fbsdatum,FBSCropData fbsd,double area){
		if ( area == 0 ){ return 0;};
		return fbsd.getValue(fbsdatum)/area;
	}

	/** Create a blank crop data object */
	public JFMCropData(CropType ct){
		super(ct);
		
		for(JFMCDatum d:JFMCDatum.values()){
			if (d.isIntensive){
				data.put(d, new DataValue(true));
			} else {
				data.put(d, new DataValue(false));
			}
		}
	}
	
	/** Merge data from another JFMCropData object into this one. Assumes that the two objects represent the same general 
	 * type of crop, and adds intensive data values to averageable DataValue objects and non-intensive to summable DataValue objects */
	public void increment(JFMCropData indata){
		double wgt=indata.data.get(JFMCDatum.AREA).sumValue();
		for ( Map.Entry<JFMCDatum, DataValue> entry:indata.data.entrySet()){
			JFMCDatum key=entry.getKey();
			DataValue val=entry.getValue();
			if ( key.isIntensive){
				data.get(key).add(val.avValue(),wgt);
			} else {
				data.get(key).add(val.sumValue());
			}
		}
	}
	
}